<?php
/**
 * crcl/base
 *
 * Copyright 2013 CRCL - André Sabosch - info@crcl.de
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace crcl\base\database\container;

interface IDynamodb
{
  public function select($sTable, $hash, $range = \NULL);
  public function insert($sTable, $aData);
  public function delete($sTable, $hash, $range = \NULL);

  //public function update($sTable, $data, $hash, $range = \NULL);

}

class ContainerDynamodb extends Base implements IDynamodb
{

  public function select($sTable, $hash, $range = \NULL)
  {
    $this->connect();

    $oResponse = $this->oDatabase->get_item(
      array(
        'TableName' => $sTable,
        'Key' =>
          array(
            'HashKeyElement' =>
              array(
                \AmazonDynamoDB::TYPE_STRING => $hash
              )
          )
       )
    );

    if (!$oResponse->isOK())
    {
      throw new Exception('Select error',
        Exception::ERROR_DYNAMODB_SELECT,
        array(
          'message' => $oResponse->body->Message,
          'response' => $oResponse
        )
      );
    }

    if (!empty($oResponse->body->Item))
    {
      $aResponse = $oResponse->body->Item->to_array()->getArrayCopy();
      $aResult = $this->formatFrom($aResponse);
      $this->aData[0] = $aResult;

      return $this;
    }
    throw new Exception('Key does not exist',
      Exception::ERROR_DYNAMODB_NOTEXIST,
      array('table' => $sTable, 'key' => $hash));
  }

  public function insert($sTable, $aData)
  {
    $this->connect();

    $aData = $this->formatTo($aData);

    $oResponse = $this->oDatabase->put_item(
      array(
        'TableName' => $sTable,
        'Item' => $aData));

    if (!$oResponse->isOK())
    {
      throw new Exception('Insert error',
        Exception::ERROR_DYNAMODB_INSERT,
        array(
          'message' => $oResponse->body->Message,
          'response' => $oResponse
        )
      );
    }

    return $this;
  }

  public function delete($sTable, $hash, $range = \NULL)
  {
    $this->connect();

    $oResponse = $this->oDatabase->delete_item(
      array(
        'TableName' => $sTable,
        'Key' =>
          array(
            'HashKeyElement' =>
              array(
                \AmazonDynamoDB::TYPE_STRING => $hash
              )
          )
      )
    );

    if (!$oResponse->isOK())
    {
      throw new Exception('Delete error',
        Exception::ERROR_DYNAMODB_DELETE,
        array(
          'message' => $oResponse->body->Message,
          'response' => $oResponse
        )
      );
    }

    return $this;
  }

  /** PRIVATE *************************************************************************************/

  private function formatTo($aData)
  {
    foreach ($aData as $key => $value)
    {
      if (\is_int($value))
      {
        $aData[$key] = array(\AmazonDynamoDB::TYPE_NUMBER => $value);
      }
      else
      {
        $aData[$key] = array( \AmazonDynamoDB::TYPE_STRING => $value);
      }
    }
    return $aData;
  }

  private function formatFrom($aData)
  {
    $aResult = array();
    foreach ($aData as $key => $aValue)
    {
      foreach ($aValue as $type => $value)
      {
        if ($type == 'S')
        {
          $aResult[$key] = (string)$value;
        }
        if ($type == 'N')
        {
          $aResult[$key] = (int)$value;
        }
      }
    }
    return $aResult;

     /*
      * gut?

          {
            if (\strpos($value, '(bool)'))
            {
              if ($value == '(bool)0')
              {
                $value = \FALSE;
              }
              else
              {
                $value = \TRUE;
              }
            }

      */
  }


  private function connect()
  {
    if (!$this->isConnected())
    {
      $aOptions = array(
        'certificate_authority' => \TRUE,
        'default_cache_config'  => 'apc',
        'key'                   => $this->oDsn->getUser(),
        'secret'                => $this->oDsn->getPassword()
      );
      $this->oDatabase = new \AmazonDynamoDB($aOptions);
      $this->oDatabase->setRegion($this->oDsn->getHost());
      $this->bConnected = \TRUE;
    }
  }
}